<!-- 
	10w大数据表格, 秒级渲染
 -->
<template>
    <div class="page">
        <div v-if="showToolbar" class="page-toolbar" :style="{ height: `${config.rowHeight || 36}px` }">
            <div class="page-toolbar__left">
                <el-button
                    v-for="item in toolbarButtons"
                    :key="item.label"
                    :type="item.type"
                    :icon="item.icon"
                    text
                    @click="() => handleEvent(item)">
                    {{ item.label }}
                </el-button>
                <FieldFilter
                    :fields="fields"
                    @change="handleFilterChange">
                </FieldFilter>
            </div>
        </div>
        <div class="page-main" :style="{ height: `${tableHeight}px` }">
            <el-auto-resizer>
                <template #default="{ height, width }">
                    <el-table-v2
                        :columns="showColumns"
                        :data="state.tableData"
                        :width="width"
                        :height="height"
                        :row-height="config.rowHeight || 36"
                        :header-height="config.headerHeight || 36"
                        :footer-height="config.footerHeight || 36"
                        :row-event-handlers="rowRventHandlers"
                        size="small"
                        fixed>
                        <template #footer>
                            <div class="footer">
                                <div>
                                    <span>共 {{ state.tableData.length }} 条记录</span>
                                    <span v-if="config.selection && selectionLen">, 已选择 {{ selectionLen }} 条</span>
                                </div>
                            </div>
                        </template>
                    </el-table-v2>
                </template>
            </el-auto-resizer>
            <DrawerForm
                v-if="dialog.visible"
                :options="dialog"
                @closed="dialogFormClosed">
            </DrawerForm>
        </div>
    </div>
</template>

<script setup lang="tsx">
import { type Fetch } from './Form.vue'
export interface Options {
    config: Config
    body: Body
}
interface Config {
    edit?: boolean | Edit
    showToolbar?: boolean
    no?: boolean
    selection?: boolean
    rowHeight?: number
    padding?: number
    headerHeight?: number
    footerHeight?: number
    fetch?: Fetch
    headerCellRenderer?: (p: any) => any
}
interface Body {
    toolBar?: any[]
    column?: any[]
}

interface Edit {
    update: Fetch | ((p: any) => any)
}

import { computed, ref, toRaw } from 'vue'
import UI from './UI.vue'
import DrawerForm from './DrawerForm.vue'
import CellSelectionV2 from './CellSelectionV2.vue'
import useWindowHeight from './hooks/useWindowHeight'
import { isStr, msg, eventCenter, tableFormat, log } from './utils'
import useTableV2 from './hooks/useTableV2'
import FieldFilter from './FieldFilter.vue'

const props = defineProps({
    options: {
        type: Object,
        default: () => ({})
    }
})
const config = props.options.config || {}
const body = props.options.body || {}

const {
    state,
    dialog,
    action,
    dialogFormClosed,
} = useTableV2(config, body)

const defaultPadding = 15
const padding = computed(() => config.padding >= 0 ? `${config.padding}px` : `${defaultPadding}px`)
const toolbarButtons = computed(() => body.toolBar || [])
const showToolbar = computed(() => toolbarButtons.value.length)
const selectionLen = computed(() => state.tableData.filter(item => item.checked).length)
const columns = computed(() => {
    const _columns = body.column
        .map((item: any, index: number) => {
            const {label, common, form, ..._item} = item
            return {
                ..._item,
                dataKey: item.key,
                title: label,
                ...common ? common : {},
                ...form
                    ? {
                        ...form,
                        controls:  form.ui === 'input-number' ? false : undefined,
                        valueFormat: form.ui === 'date'
                            ? 'YYYY-MM-DD'
                            : form.ui === 'datetime'
                                ? 'YYYY-MM-DD HH:mm:ss'
                                : form.valueFormat,
                        ui: config.edit ? form.ui || 'input' : undefined,
                        cellRenderer: config.edit ? cellRenderer : undefined,
                        headerCellRenderer: config.headerCellRenderer || form.headerCellRenderer || undefined
                    }
                    : {},
            }
        })
    // 序号列
    if (config.no) {
        _columns.unshift({
            key: 'no',
            title: '序号',
            width: 60,
            align: 'center',
            fixed: true,
            cellRenderer: ({ rowIndex }: any) => {
                return <div>{ rowIndex + 1 }</div>
            },
        })
    }
    // 复选框
    if (config.selection) {
        _columns.unshift({
            key: 'selection',
            width: 60,
            fixed: true,
            align: 'center',
            cellRenderer: ({ rowData, rowIndex }: any) => {
                const onChange = (value: boolean) => rowData.checked = value
                const onAction = ({ type, index }: any) => {
                    action.insert({ type, index })
                }
                return <CellSelectionV2
                    checked={rowData.checked}
                    rowIndex={rowIndex} 
                    onChange={onChange}
                    onAction={onAction}/>
            },
            headerCellRenderer: () => {
                const _data = toRaw(state.tableData)
                const onChange = (value: boolean) => {
                    state.tableData = _data.map((row: any) => {
                        row.checked = value
                        return row
                    })
                }
                const allSelected = state.tableData.every((row: any) => row.checked)
                const containsChecked = state.tableData.some((row: any) => row.checked)
                return (
                    <SelectionCell
                        value={allSelected && _data.length > 0}
                        intermediate={containsChecked && !allSelected}
                        onChange={onChange}
                    />
                )
            },
        })
    }
    return _columns
})

const showColumns = computed(() => {
    return columns.value.filter((item: any) => [undefined, false].includes(item.hide))
})
const fields = computed(() => {
    return body.column
        .filter((item: any) => [undefined, false].includes(item.hide))
        .map((item: any) => ({
            label: item.label,
            ui: item.form.ui,
            value: item.key
        }))
})

// 单元格渲染
const cellRenderer = (params: any) => {
    const cellRef = ref() // 定义组件ref方法
    const { rowData, column, rowIndex } = params
    const editingKey = `${column.dataKey}${rowIndex}Editing`
    const onEvent = ({ item, form, eventName }: any) => {
        if (['change'].includes(eventName)) {
            onChange(form[item.key])
        } else if (['blur'].includes(eventName)) {
            onExitEditMode()
        }
    }
    const onChange = (value: any) => {
        rowData[column.dataKey!] = value
        config.edit && config.edit.update && config.edit.update({
            row: params,
            msg,
            data: state.tableData,
            change: true
        })
        // console.log('cellRef', cellRef.value)
    }
    const onEnterEditMode = () => {
        rowData[editingKey] = true
    }
    const onExitEditMode = () => {
        rowData[editingKey] = false
        config.edit && config.edit.update && config.edit.update({
            row: params,
            msg,
            data: state.tableData
        })
    }
    const setRef = (el: any) => {
        cellRef.value = el // 传递组件ref方法
        if (el) {
            el.focus?.()
        }
    }
    return rowData[editingKey] || ['checkbox', 'cell-upload', 'cell-rich-editor'].includes(column.ui)
        ? (
            column.ui &&
            <UI
                forwardRef={ setRef }
                item={ column }
                form={ rowData }
                onEvent={ onEvent }
                checkboxPadding={ true }/>
        )
        : <div class={['cell-handle']} onClick={onEnterEditMode} >
            {
                column.format && isStr(column.format)
                    ? tableFormat[column.format] && tableFormat[column.format]({ row: rowData, item: column , multiple: column.multiple})
                    : rowData[column.dataKey!]
            }
        </div>
}

// 复选框组
const SelectionCell= ({ value, intermediate = false, onChange }: any) => {
    return <el-checkbox onChange={onChange} modelValue={value} indeterminate={intermediate} />
}

// 表格高度
const { tableHeight } = useWindowHeight(true, (_config: any) => {
    const gutterH = (config.padding >= 0 ? config.padding : defaultPadding) * 2
    const toolbarBorderH = 1
    const toolbarH = showToolbar.value ? (config.headerHeight || 36) : 0
    return _config
        ? _config.headerBar.height + (_config.tabBar && _config.tabBar.show ? _config.tabBar.height : 0) + toolbarH + toolbarBorderH + gutterH
        : 0 + toolbarH + toolbarBorderH + gutterH
})

const handleFilterChange = (value: any) => {
    action.query(value)
}

const handleEvent = (item: any) => {
    const params: any = { eventName: 'click', item }
    if (config.selection) params.selection = toRaw(state.tableData).filter(item => item.checked)
    eventCenter(params, action)
}

// 行事件处理
const rowRventHandlers = {
    // onClick: (obj: any) => {
    //     console.log('onClick', obj);
    // },
    // onContextmenu: (obj: any) => {
    //     console.log('onContextmenu', obj);
    // },
    // onDblclick: (obj: any) => {
    //     console.log('onDblclick', obj);
    // },
    // onMouseenter: (obj: any) => {
    //     console.log('onMouseenter', obj);
    // },
    // onMouseleave: (obj: any) => {
    //     console.log('onMouseleave', obj);
    // },
}

</script>

<style lang="scss" scoped>
.page{
    --zui-padding: v-bind(padding);
    padding: var(--zui-padding);
    &-toolbar{
        background-color: #fff;
        margin-bottom: 1px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 5px;
        &__left{
            display: flex;
            line-height: 1;
            :deep(.el-button) {
                height: 26px;
                padding: 6px 10px 6px 8px;
            }
            :deep(.el-button+.el-button) {
                margin-left: 6px;
            }
        }
    }
    &-main{
        :deep(.cell-handle){
            width: 100%;
            height: 32px;
            line-height: 30px;
            padding: 0 10px;
            cursor: pointer;
            border: 1px solid rgba($color: #000000, $alpha: 0);
            border-radius: var(--el-border-radius-base);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        :deep(.cell-handle:hover){
            border: 1px solid var(--el-color-primary);
        }
        :deep(.el-table-v2__row-cell) {
            padding: 0 2px;
        }
        :deep(.el-table-v2__header-cell) {
            padding: 0 10px;
        }
    }
}
.footer{
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    border-top: var(--el-table-border);
    background-color: #f5f7fa;
    background-color: #fff;
    font-size: 12px;
}
</style>